﻿using Quartz;
using Quartz.Spi;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using ThresholdAssistant.NLogSdk;
using ThresholdAssistant.Tools;

namespace ThresholdAssistant.Handler
{
    /// <summary>
    /// 调度中心
    /// </summary>
    public class SchedulerCenter
    {
        private readonly IJobFactory _jobFactory;
        private readonly ISchedulerFactory _schedulerFactory;
        private IScheduler _scheduler;
        private static readonly List<IBaseJob> Jobs = new List<IBaseJob>();
        private readonly IServiceProvider _serviceProvider;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="jobFactory"></param>
        /// <param name="schedulerFactory"></param>
        /// <param name="serviceProvider"></param>
        public SchedulerCenter(IJobFactory jobFactory, ISchedulerFactory schedulerFactory, IServiceProvider serviceProvider)
        {
            _jobFactory = jobFactory;
            _schedulerFactory = schedulerFactory;
            _serviceProvider = serviceProvider;
            InitJobs();
        }

        public void InitJobs()
        {
            //用于实现属性注入的基础接口
            Type baseType = typeof(IJob);
            //用于实现属性注入的基础接口
            Type baseType1 = typeof(IBaseJob);
            //扫描当前执行目录下所有存在继承于IAutofacBase接口的程序集
            Assembly[] assemblyList = AssemblyUtil.GetAssemblyList(baseType);
            Assembly[] assemblyList1 = AssemblyUtil.GetAssemblyList(baseType1);
            if (assemblyList == null || assemblyList.Length <= 0)
                return;
            var assemblyList2 = assemblyList.Intersect(assemblyList1).ToList();
            var types = assemblyList2.SelectMany(x => x.GetTypes()).Where(type => type != baseType && baseType.IsAssignableFrom(type)).ToList();
            foreach (var type in types)
            {
                var job = _serviceProvider.GetService(type);
                if (job != null)
                {
                    Jobs.Add(job as IBaseJob);
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public async Task StartScheduler()
        {
            //1、从工厂获取调度程序实例
            _scheduler = await _schedulerFactory.GetScheduler();
            // 替换默认工厂
            _scheduler.JobFactory = this._jobFactory;

            //2、打开调度器
            await _scheduler.Start();
            foreach (var Job in Jobs)
            {
                NLogUtil.Debug($"{Job.JobName} {Job.Cron}");
                await StartScheduler(Job);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="t"></param>
        /// <returns></returns>
        public async Task StartScheduler<T>(T t) where T : IBaseJob
        {
            if (string.IsNullOrWhiteSpace(t.Cron))
            {
                NLogUtil.Error($"{t.JobName} Cron未配置");
                return;
            }
            //3、定义作业详细信息并将其与任务相关联
            var job = JobBuilder.Create(t.GetType())
                .WithIdentity(t.JobName, t.JobGroupName)
                .Build();

            //4、配置触发条件
            ITrigger trigger = TriggerBuilder.Create()
                .WithIdentity(t.JobName, t.JobGroupName)
                .StartNow()
                 .WithCronSchedule(t.Cron)
                .Build();

            //5、将作业与触发条件添加到调度实例并进行关联
            await _scheduler.ScheduleJob(job, trigger);
        }

        /// <summary>
        /// 停止调度
        /// </summary>
        public void StopScheduler()
        {
            NLogUtil.Warn("【停止调度】");
            _scheduler = null;
        }
    }
}
